package control

import (
    "github.com/gorilla/websocket"
    "net/http"
    "net/url"
    "time"
    "recorder/internal"
    "recorder/log"
)

const (
    handshakeTimeout = 3 * time.Second
    reconnectTimeout = 3 * time.Second
)

type Client struct {
    config *internal.Config
    done   chan struct{}
    C      chan *Conn
}

func NewClient(config *internal.Config) *Client {
    return &Client{
        config: config,
        done:   make(chan struct{}),
        C:      make(chan *Conn),
    }
}

func (c *Client) Close() {
    close(c.done)
}

func (c *Client) Connect() {
restart:
    select {
    case <-c.done:
        return
    default:
    }

    u := url.URL{Scheme: "ws", Host: c.config.Addr, Path: "/control"}
    log.Info("client: connect to %v", c.config.Addr)
    d := &websocket.Dialer{
        HandshakeTimeout: handshakeTimeout,
    }
    h := http.Header{}
    h.Add("X-Conn-Id", c.config.Id)
    ws, _, err := d.Dial(u.String(), h)
    if err != nil {
        log.Warning("client: connect to %v error: %v, retry after %v", c.config.Addr, err, reconnectTimeout)
        time.Sleep(reconnectTimeout)
        goto restart
    }
    log.Info("client: connected to %v", c.config.Addr)
    conn := NewConn(ws, c.config.Id)
    go conn.Run()
    select {
    case <-c.done:
        log.Warning("client: closed while new connection established")
        conn.Close()
    case c.C <- conn:
    }
}
